import GCJ_CLASS_TYPE = require('./../../common/GCJ_CLASS_TYPE');
import CommonModel = require('./../../common/model/CommonModel');
import DEFINE = require('./../../common/DEFINE');
import Serializer = require('./../base/Serializer');
import SJGPageDescribe = require('./../base/SJGPageDescribe');
import GroupObj = require('./../obj/GroupObj');
import TextObj = require('./../obj/TextObj');
import ImageObj=require('./../obj/ImageObj');
import GraphObj=require('./../obj/GraphObj');
import TextExtObj=require('./../obj/TextExtObj');
import ObjBase=require('./../obj/ObjBase');
import Parser = require('./../base/Parser');
import ParserOfUserReplaces = require('./../base/ParserOfUserReplaces');
import GlobalData = require('./../../z/GlobalData');
import SJGReplaceGroup = require('./../replace/SJGReplaceGroup');
import SJGReplaceItemBase = require('./../replace/SJGReplaceItemBase');
import SJGReplaceItemText = require('./../replace/SJGReplaceItemText');
import SJGReplaceItemImage = require('./../replace/SJGReplaceItemImage');
import SJGReplaceItemChart= require('./../replace/SJGReplaceItemChart');
import SJGReplaceItemTable= require('./../replace/SJGReplaceItemTable');
import SJGReplaceItemTitleText=require('./../replace/SJGReplaceItemTitleText');
import SJGSubGroupText=require('./../replace/SJGSubGroupText');
import SJGSubGroupImageText=require('./../replace/SJGSubGroupImageText');
import SJGSubGroupImageTextOld=require('./../replace/SJGSubGroupImageTextOld');
import SJGTypeSet  =require('./../../typeset/SJGTypeSet');
import ObjManager = require('./ObjManager');
import PageInfo=require('./../../common/PageInfo');
import SJGNode=require('./../../common/tg/SJGNode');
import SJGNodeV3=require('./../../common/tg3/SJGNodeV3');
import ObjLink = require('./../base/ObjLink');

var ItbGraphModel=require('./../../../../common/mysql/mapping/ItbGraphModel');
var FileDownLoader=require('./../../../../common/util/FileDownLoader');


var fs  = require( 'fs'); // 

var async  = require( 'async'); // 同步控制
var CONFIG = require('./../../../../common/config');
var CommonUtil=require('./../../../../common/util/CommonUtil');
var rpcFunc  =require('./../../../routes/rpcSrv/rpcFunc.js');
export  = SJGPage;



/**
 *
 * @author 
 *
 */
class SJGPage extends Serializer{
    public describe: SJGPageDescribe = new SJGPageDescribe();
    public root: GroupObj = new GroupObj(); // 一个Page必定有一个root组对象
    public replaces: Array<Object> = new Array<Object>(); // 本页面的可替换部分
    public replaces2: Array<Object> = new Array<Object>(); // 本页面的可替换部分
    public arrLink: Array<ObjLink>=new Array<ObjLink>(); // 本页关联对象id的列表

    
    public thumbUrl: string=null;// 排版服务auto使用，不用序列化
    
	public constructor(g?) {
        super(g);
        
        this.ct = GCJ_CLASS_TYPE.CLASS_TYPE_SJGPage;
        
        //  传递doc全局域，为兼容nodejs
        this.root.setGlobalData(this.getGlobalData());
        
        // 加载旧文档时，在fromJson里处理
        if (this.getGlobalData().docStatus() == DEFINE.DOC_STATUS_EDIT) {
            this.getGlobalData().objManager().saveObject( this.root );// 记入对象管理器
        }
	}
	
    // 从json对象(注意不是json字符串)中解析
    public fromJson(jsonObj, versionId) { 
        super.fromJson(jsonObj,versionId);
                        
        this.describe = Parser.fromUnknownJson( jsonObj.describe ,versionId);
        this.root = <GroupObj> Parser.fromUnknownJson( jsonObj.root ,versionId, this.getGlobalData());
        
        this.replaces.splice(0,this.replaces.length);
        if(jsonObj.hasOwnProperty('replaces')&&jsonObj.replaces) {
            for (var i = 0;i < jsonObj.replaces.length;i++) {
                var repGrp = new SJGReplaceGroup(this.getGlobalData());
                repGrp.fromJson(jsonObj.replaces[i],versionId);
                this.replaces.push(repGrp);
            }
        }

        // arrLink
        this.arrLink.splice(0,this.arrLink.length);
        if(jsonObj.hasOwnProperty('arrLink')&&jsonObj.arrLink){
            for(var i=0;i<jsonObj.arrLink.length;i++) {
                var link=new ObjLink();
                link.fromJson(jsonObj.arrLink[i],versionId);
                this.arrLink.push(link);
            }
        }
        
        // 加载文档时
        if (this.getGlobalData().docStatus() == DEFINE.DOC_STATUS_LOADING) {
            this.getGlobalData().objManager().saveObject( this.root );// 记入对象管理器
        }
    }
    // 从json对象(注意不是json字符串)中解析
    public fromJsonOfTG(jsonObj, versionId) {
        super.fromJson(jsonObj,versionId);

        this.describe = Parser.fromUnknownJson( jsonObj.describe ,versionId);
        this.root = <GroupObj> Parser.fromUnknownJson( jsonObj.root ,versionId, this.getGlobalData());


        if(jsonObj.hasOwnProperty('replaces')&&jsonObj.replaces) {
            for (var i = 0;i < jsonObj.replaces.length;i++) {
                var n = new SJGNode();
                n.fromJson(jsonObj.replaces[i],versionId);
                this.replaces.push(n);
            }
        }
        if(jsonObj.hasOwnProperty('replaces2')&&jsonObj.replaces2) {
            for (var i = 0;i < jsonObj.replaces2.length;i++) {
                var n = new SJGNodeV3();
                n.fromJson(jsonObj.replaces2[i],versionId);
                this.replaces2.push(n);
            }
        }

        // arrLink
        this.arrLink.splice(0,this.arrLink.length);
        if(jsonObj.hasOwnProperty('arrLink')&&jsonObj.arrLink){
            for(var i=0;i<jsonObj.arrLink.length;i++) {
                var link=new ObjLink();
                link.fromJson(jsonObj.arrLink[i],versionId);
                this.arrLink.push(link);
            }
        }

        // 加载文档时
        if (this.getGlobalData().docStatus() == DEFINE.DOC_STATUS_LOADING) {
            this.getGlobalData().objManager().saveObject( this.root );// 记入对象管理器
        }
    }
    // 转成json字符串
    public toJson():string {
        // 去掉父json字符串的头尾
        var superJson = super.toJson();
        superJson = superJson.substr(1,superJson.length-2);
                        
        var ret = '{';
        ret +=superJson;
                                
        // describe
        ret +=',';
        ret += '"describe":';
        ret += this.describe.toJson();
            
        // root
        ret +=',';
        ret += '"root":';
        ret += this.root.toJson();
        
        // replaces
        if(this.replaces){
            ret += ',';
            ret += '"replaces":'
            ret += '[';
            for (var i = 0; i < this.replaces.length; i++) {
                if(i>0){
                    ret += ',';
                }
                ret += this.replaces[i].toJson();
            }
            ret += ']';
        }

        // replaces2
        if(this.replaces2){
            ret += ',';
            ret += '"replaces2":'
            ret += '[';
            for (var i = 0; i < this.replaces2.length; i++) {
                if(i>0){
                    ret += ',';
                }
                ret += this.replaces2[i].toJson();
            }
            ret += ']';
        }


        // link
        if(this.arrLink) {
            ret+=',';
            ret+='"arrLink":';
            ret+='[';
            for(var i=0;i<this.arrLink.length;i++) {
                if(i>0) {
                    ret+=',';
                }
                ret+=this.arrLink[i].toJson();
            }
            ret+=']';
        }
        
        ret+='}';
        return ret;
    }

    //###################################################### ADD 2017-09-06 START
    // 从“微调”json对象(注意不是json字符串)中解析
    public fromJsonOfFineTune(jsonObj, versionId) {
        super.fromJson(jsonObj,versionId);

        this.root = <GroupObj> Parser.fromUnknownJson(jsonObj.root ,versionId, this.getGlobalData());

        if(jsonObj.hasOwnProperty('replaces')&&jsonObj.replaces) {
            for (var i = 0;i < jsonObj.replaces.length;i++) {
                var n = new SJGNode();
                n.fromJson(jsonObj.replaces[i],versionId);
                this.replaces.push(n);
            }
        }
        if(jsonObj.hasOwnProperty('replaces2')&&jsonObj.replaces2) {
            for (var i = 0;i < jsonObj.replaces2.length;i++) {
                var n = new SJGNodeV3();
                n.fromJson(jsonObj.replaces2[i],versionId);
                this.replaces2.push(n);
            }
        }
    }
    // 转成“微调”使用的json字符串
    public toJsonOfFineTune():string{
        var ret='{';

        // root
        ret+='"root":';
        ret+=this.root.toJsonOfMinTextExt();

        // replaces
        if(this.replaces) {
            ret+=',';
            ret+='"replaces":'
            ret+='[';
            for(var i=0;i<this.replaces.length;i++) {
                if(i>0) {
                    ret+=',';
                }
                ret+=this.replaces[i].toJson();
            }
            ret+=']';
        }

        // replaces2
        if(this.replaces2) {
            ret+=',';
            ret+='"replaces2":'
            ret+='[';
            for(var i=0;i<this.replaces2.length;i++) {
                if(i>0) {
                    ret+=',';
                }
                ret+=this.replaces2[i].toJson();
            }
            ret+=']';
        }

        ret+='}';
        return ret;
    }
    //###################################################### ADD 2017-09-06 END

    // 转成json字符串（仅replaces）
    public toJsonReplaces():string {
        var ret = '[';
        for (var i = 0; i < this.replaces.length; i++) {
            if(i>0){
                ret += ',';
            }
            ret += this.replaces[i].toJson();
        }
        ret += ']';
        return ret;
    }
    
    // 获取本页所包含replace对象标记
    public getReplaceObjTag():number {
        var tag: number=SJGReplaceGroup.TAG_NONE;
        
        if(this.replaces&&this.replaces.length>0) {
            for(var i=0;i<this.replaces.length;i++) {
                var sjgRepGrp: SJGReplaceGroup=this.replaces[i];

                // 标题组
                if(sjgRepGrp.kind==SJGReplaceGroup.TITLEGROUP) {
                    for(var n in sjgRepGrp.value) {
                        var title: SJGReplaceItemText=<SJGReplaceItemText>sjgRepGrp.value[n];
                        if(title.type==SJGReplaceItemBase.TYPE_PAGE_TITLE)
                            tag=tag|SJGReplaceGroup.TAG_TITLE;
                        else if(title.type==SJGReplaceItemBase.TYPE_PAGE_SUBTITLE)
                            tag=tag|SJGReplaceGroup.TAG_SUB_TITLE;
                    }
                    
                // 备注组
                } else if(sjgRepGrp.kind==SJGReplaceGroup.COMMENTGROUP) {
                    for(var n in sjgRepGrp.value) {
                        var cmt: SJGReplaceItemText=<SJGReplaceItemText>sjgRepGrp.value[n];
                        if(cmt.type==SJGReplaceItemBase.TYPE_PAGE_COMMENT) {
                            tag=tag|SJGReplaceGroup.TAG_COMMENT;
                        }
                    }
                    
                // 增强文字组
                } else if(sjgRepGrp.kind==SJGReplaceGroup.TEXTGROUP2) {
                    if(sjgRepGrp.value && sjgRepGrp.value.length>0) {
                        tag=tag|SJGReplaceGroup.TAG_TEXT;
                    }
                    
                // 图文组2
                } else if(sjgRepGrp.kind==SJGReplaceGroup.IMAGETEXTGROUP2) {
                    if(sjgRepGrp.value&&sjgRepGrp.value.length>0) {
                        tag=tag|SJGReplaceGroup.TAG_IMG_TXT;
                    }
                    
                // 图片组
                } else if(sjgRepGrp.kind==SJGReplaceGroup.IMAGEGROUP) {
                    if(sjgRepGrp.value&&sjgRepGrp.value.length>0) {
                        tag=tag|SJGReplaceGroup.TAG_IMAGE;
                    }
                    
                // 图表组
                } else if(sjgRepGrp.kind==SJGReplaceGroup.CHARTGROUP) {
                    if(sjgRepGrp.value&&sjgRepGrp.value.length>0) {
                        tag=tag|SJGReplaceGroup.TAG_CHART;
                    }
                    
                // 表格组
                } else if(sjgRepGrp.kind==SJGReplaceGroup.TABLEGROUP) {
                    if(sjgRepGrp.value&&sjgRepGrp.value.length>0) {
                        tag=tag|SJGReplaceGroup.TAG_TABLE;
                    }
                }
            }
        }
        
        return tag;
    }
    
    // 增加测试页
    public addTestData(){
        // 增加标题A、副标题B、普通文字C及其文字组CC、图片D及其图片组DD
        var A: TextObj=new TextObj();
        this.getGlobalData().objManager().saveObject( A );// 记入对象管理器
        A.te="标题";
        this.root.addChild(A,this.root.children.length);
        //----------        
        var B: TextObj=new TextObj();
        this.getGlobalData().objManager().saveObject( B );// 记入对象管理器
        B.te="副标题";
        this.root.addChild(B,this.root.children.length);
        //----------        
        var C: TextObj=new TextObj();
        this.getGlobalData().objManager().saveObject( C );// 记入对象管理器
        C.te="普通文字";
        
        var CC: GroupObj=new GroupObj();
        this.getGlobalData().objManager().saveObject( CC );// 记入对象管理器
        CC.addChild(C,CC.children.length);
        this.root.addChild(C,this.root.children.length);
                
        //----------  
        var D: ImageObj = new ImageObj();
        this.getGlobalData().objManager().saveObject( D );// 记入对象管理器
        D.source = "http://127.0.0.1:3001/images/1.jpg";
        
        var DD: GroupObj=new GroupObj();
        this.getGlobalData().objManager().saveObject( DD );// 记入对象管理器
        CC.addChild(D,DD.children.length);
        this.root.addChild(DD,this.root.children.length);
                
        // 添加一个可替换数组，标题组，含有主标题、副标题，分别对应文字A，文字B
        // 添加一个可替换数组，文字组，含有两个文字，一个对应文字C，一个是新增文字E
        // 添加一个可替换数组，图片组，含有两张图片，一个赌赢图片D，一个是新图片F
        
        var replace: SJGReplaceGroup=new SJGReplaceGroup();
        this.replaces.push(replace);
        replace.kind=SJGReplaceGroup.TITLEGROUP;
        replace.min=0;
        replace.max=2;
        replace.id=DEFINE.ID_NONE; // 标题组为固定元素，没有对应的组对象
        replace.advance.extend_style =SJGReplaceGroup.BBOX;
        replace.advance.extend_method =SJGReplaceGroup.HORIZON;
        
        
        var item: SJGReplaceItemText=new SJGReplaceItemText();
        item.type=SJGReplaceItemBase.TYPE_PAGE_TITLE;
        item.id=A.id;
        item.value="new标题";
        replace.value.push(item);
        
        var item: SJGReplaceItemText=new SJGReplaceItemText();
        item.type=SJGReplaceItemBase.TYPE_PAGE_SUBTITLE;
        item.id=B.id;
        item.value="new副标题";
        replace.value.push(item);
        
        //---------- 
        var replace: SJGReplaceGroup=new SJGReplaceGroup();
        this.replaces.push(replace);
        replace.kind=SJGReplaceGroup.TEXTGROUP;
        replace.min=1;
        replace.max=2;
        replace.id=CC.id; // 文字组有对应的组对象
        replace.advance.extend_style =SJGReplaceGroup.BBOX;
        replace.advance.extend_method =SJGReplaceGroup.HORIZON;
        
                
        var item: SJGReplaceItemText=new SJGReplaceItemText();
        item.type=SJGReplaceItemBase.TYPE_TEXT;
        item.id=C.id;
        item.value="new文字1";
        item.min=1;
        item.max=20;
        replace.value.push(item);
                
        var item: SJGReplaceItemText=new SJGReplaceItemText();
        item.type=SJGReplaceItemBase.TYPE_TEXT;
        item.id=DEFINE.ID_NONE;
        item.value="new文字2";
        item.min=1;
        item.max=20;
        replace.value.push(item);
        
        //---------- 
        var replace: SJGReplaceGroup=new SJGReplaceGroup();
        this.replaces.push(replace);
        replace.kind=SJGReplaceGroup.IMAGEGROUP;
        replace.min=1;
        replace.max=2;
        replace.id=DD.id; // 文字组有对应的组对象
        replace.advance.extend_style =SJGReplaceGroup.BBOX;
        replace.advance.extend_method =SJGReplaceGroup.HORIZON;
        
                        
        var item2: SJGReplaceItemImage=new SJGReplaceItemImage();
        item2.type=SJGReplaceItemBase.TYPE_IMAGE;
        item2.id=D.id;
        item2.value="http://127.0.0.1:3001/images/1.jpg";
        replace.value.push(item2);
                        
        var item2: SJGReplaceItemImage=new SJGReplaceItemImage();
        item2.type=SJGReplaceItemBase.TYPE_IMAGE;
        item2.id=DEFINE.ID_NONE;
        item2.value="http://127.0.0.1:3001/images/1.jpg";
        replace.value.push(item2);
        
        
        
    }
    
    // 删除某个replace[除“标题”和“副标题”外]
    public removeReplace(replaceGroupObjId:number){
        for(var i in this.replaces){
            var one: SJGReplaceGroup=this.replaces[i];
            if(one.id == replaceGroupObjId){
                this.replaces.splice(i,1);
                break;
            }
        }
    }
    // 删除“标题”或者“副标题”
    public removeReplaceTitile(replaceTitleOrSubTitleId: number) {
        for(var i in this.replaces) {
            var one: SJGReplaceGroup=this.replaces[i];
            if(one.kind==SJGReplaceGroup.TITLEGROUP) {
                for(var j in one.value){
                    var v: SJGReplaceItemText=<SJGReplaceItemText>one.value[j];
                    if(v.id == replaceTitleOrSubTitleId){
                        one.value.splice(j,1);
                        break;
                    }
                }
                break;
            }
        }
    }
    public removeReplaceTitileGrp() {
        for(var i in this.replaces) {
            var one: SJGReplaceGroup=this.replaces[i];
            if(one.kind==SJGReplaceGroup.TITLEGROUP) {
                this.replaces.splice(i,1);
                break;
            }
        }
    }
    
    // 获取页标题/副标题对象的id
    public getPageTitleIds(type: number): Array<number>{
        var ids: Array<number>=new Array<number>();
        
        for(var i in this.replaces) {
            var one: SJGReplaceGroup=this.replaces[i];
            if(one.kind==SJGReplaceGroup.TITLEGROUP) {
                for(var j in one.value) {
                    var v: SJGReplaceItemText=<SJGReplaceItemText>one.value[j];
                    if(type==SJGReplaceItemBase.TYPE_PAGE_TITLE) {
                        if(v.type==SJGReplaceItemBase.TYPE_PAGE_TITLE) {
                            ids.push(v.id);
                        }
                        
                    } else if(type==SJGReplaceItemBase.TYPE_PAGE_SUBTITLE) {
                        if(v.type==SJGReplaceItemBase.TYPE_PAGE_SUBTITLE) {
                            ids.push(v.id);
                        }

                    } else {
                        ids.push(v.id);
                    }
                }
                break;
            }
        }
    
        return ids;
    }
    
    // 删除“页备注”
    public removeReplaceCommentGrp(cmtId?: number) {
        for(var i in this.replaces) {
            var one: SJGReplaceGroup=this.replaces[i];
            if(one.kind==SJGReplaceGroup.COMMENTGROUP) {
//                for(var j in one.value) {
//                    var v: SJGReplaceItemText=<SJGReplaceItemText>one.value[j];
//                    if(v.id==cmtId) {
//                        one.value.splice(j,1);
//                        break;
//                    }
//                }
                this.replaces.splice(i,1);
                break;
            }
        }
    }
    
    // 获取本页标题的replace对象
    public getPageTitleGroup(): SJGReplaceGroup {
        var rg: SJGReplaceGroup  = null;
        for(var i in this.replaces) {
            var one = this.replaces[i];
            if(one.kind == SJGReplaceGroup.TITLEGROUP) {
                rg = one;
                break;
            }
        }
        return rg;
    }
    
    // 是否为“标题”或者“副标题”
    // 返回：
    //            0:表示不是
    //            SJGReplaceItemBase.TYPE_PAGE_TITLE：表示是标题  
    //            SJGReplaceItemBase.TYPE_PAGE_SUBTITLE：表示是副标题
    public isTitleOrSubTitle(replaceTitleOrSubTitleId: number) {
        for(var i in this.replaces) {
            var one: SJGReplaceGroup=this.replaces[i];
            if(one.kind==SJGReplaceGroup.TITLEGROUP) {
                for(var j in one.value) {
                    var v: SJGReplaceItemText=<SJGReplaceItemText>one.value[j];
                    if(v.id==replaceTitleOrSubTitleId) {
                        if(v.type==SJGReplaceItemBase.TYPE_PAGE_TITLE)
                            return SJGReplaceItemBase.TYPE_PAGE_TITLE;
                        else if(v.type==SJGReplaceItemBase.TYPE_PAGE_SUBTITLE)
                            return SJGReplaceItemBase.TYPE_PAGE_SUBTITLE;
                    }
                }
                break;
            }
        }
        return 0;
    }
    
    // 是否为“页备注”
    public isPageComment(cmtId: number):boolean {
        for(var i in this.replaces) {
            var one: SJGReplaceGroup=this.replaces[i];
            if(one.kind==SJGReplaceGroup.COMMENTGROUP) {
                for(var j in one.value) {
                    var v: SJGReplaceItemText=<SJGReplaceItemText>one.value[j];
                    if(v.id==cmtId) {
                        return true;
                    }
                }
                break;
            }
        }
        return false;
    }
    
    // 是否含有页标题或页副标题
    // 参数chkType:
    //   1. chkType = SJGReplaceItemBase.TYPE_PAGE_TITLE: 只检查是否有页标题
    //   2. chkType = SJGReplaceItemBase.TYPE_PAGE_SUBTITLE: 只检查是否有页副标题
    //   3. 1、2以外的情况: 检查是否含有标题或副标题
    public hasTitleOrSubTitle(chkType: number = 0):boolean {
        var bRet:boolean = false;
        
        for(var i in this.replaces) {
            var one: SJGReplaceGroup = this.replaces[i];
            
            if(one.kind == SJGReplaceGroup.TITLEGROUP) {
                for(var j in one.value) {
                    var v: SJGReplaceItemText = <SJGReplaceItemText>one.value[j];
                    
                    if(chkType == SJGReplaceItemBase.TYPE_PAGE_TITLE) {
                        if(v.type == SJGReplaceItemBase.TYPE_PAGE_TITLE) {
                            bRet = true;
                            break;
                        }
                    } else if(chkType == SJGReplaceItemBase.TYPE_PAGE_SUBTITLE) {
                        if(v.type == SJGReplaceItemBase.TYPE_PAGE_SUBTITLE) {
                            bRet = true;
                            break;
                        }
                    } else {
                        bRet = true;
                        break;
                    }
                }
                
                break;
            }
        }
        
        return bRet;
    }
    
    // 获取页备注对象
    public getPageComment() : number {
        for(var i in this.replaces) {
            var one: SJGReplaceGroup=this.replaces[i];
            if(one.kind==SJGReplaceGroup.COMMENTGROUP) {
                for(var j in one.value) {
                    var v: SJGReplaceItemText=<SJGReplaceItemText>one.value[j];
                    if(v.type==SJGReplaceItemBase.TYPE_PAGE_COMMENT) {
                        return v.id;
                    }
                }
                break;
            }
        }
        return null;
    }
    
    // 是否为顶级子对象
    public isTopChild(objId:number):Boolean{
        for(var i in this.root.children){
            var obj: ObjBase=this.root.children[i];
            if(obj.id == objId){
                return true;
            }
        }
        return false;
    }
    // 是否为replaceGroup的子
    public isChildOfReplaceGroup(objId:number):Boolean{
        for(var i in this.replaces){
            var replace: SJGReplaceGroup=this.replaces[i];
            for(var j in replace.value){
                var replaceItemBase: SJGReplaceItemBase=replace.value[j];
                if(replaceItemBase.id == objId){
                    return true;
                }
            }
        }
        return false;
    }
    // 如果是replaceGroup的子，则返回该子item
    public getReplaceItem(objId: number): SJGReplaceItemBase {
        for(var i in this.replaces) {
            var replace: SJGReplaceGroup = this.replaces[i];
            for(var j in replace.value) {
                var replaceItemBase: SJGReplaceItemBase = replace.value[j];
                if(replaceItemBase.id == objId) {
                    return replaceItemBase;
                }else {
                    // 带小标题图文组
                    if(replaceItemBase instanceof SJGSubGroupText){
                        var rit2 = <SJGSubGroupText>replaceItemBase;
                        for(var n in rit2.value){
                            var hlt: SJGReplaceItemTitleText = rit2.value[n];
                            if (hlt.id == objId) {
                                return hlt;
                            }
                        }
                    // 带小标题图文组
                    } else if (replaceItemBase instanceof SJGSubGroupImageText) {
                        var riit2 = <SJGSubGroupImageText>replaceItemBase;
                        if (riit2.image.id == objId){
                            return riit2.image;
                        }
                        for(var n in riit2.textArr.value) {
                            var hlt: SJGReplaceItemTitleText = riit2.textArr.value[n];
                            if(hlt.id == objId) {
                                return hlt;
                            }
                        }
                    // 普通图文组
                    } else if(replaceItemBase instanceof SJGSubGroupImageTextOld) {
                        var riit = <SJGSubGroupImageTextOld>replaceItemBase;
                        if(riit.image.id == objId) {
                            return riit.image;
                        }
                        if(riit.text.id == objId) {
                            return riit.text;
                        }
                    }
                }
            }
        }
        return null;
    }
    
    // 查找编组对象
    public getReplaceGroup(objId: number): SJGReplaceGroup {
        for(var i in this.replaces) {
            var replace: SJGReplaceGroup=this.replaces[i];
            // check编组本身
            if(replace.id==objId) {
                return replace;
            }
            
            // check编组子对象
            for(var j in replace.value) {
                var replaceItemBase: SJGReplaceItemBase=replace.value[j];
                if(replaceItemBase.id==objId) {
                    return replace;
                } else {
                    // 带小标题图文组
                    if(replaceItemBase instanceof SJGSubGroupText) {
                        var rit2=<SJGSubGroupText>replaceItemBase;
                        for(var n in rit2.value) {
                            var hlt: SJGReplaceItemTitleText=rit2.value[n];
                            if(hlt.id==objId) {
                                return replace;
                            }
                        }
                        // 带小标题图文组
                    } else if(replaceItemBase instanceof SJGSubGroupImageText) {
                        var riit2=<SJGSubGroupImageText>replaceItemBase;
                        if(riit2.image.id==objId) {
                            return replace;
                        }
                        for(var n in riit2.textArr.value) {
                            var hlt: SJGReplaceItemTitleText=riit2.textArr.value[n];
                            if(hlt.id==objId) {
                                return replace;
                            }
                        }
                        // 普通图文组
                    } else if(replaceItemBase instanceof SJGSubGroupImageTextOld) {
                        var riit=<SJGSubGroupImageTextOld>replaceItemBase;
                        if(riit.image.id==objId) {
                            return replace;
                        }
                        if(riit.text.id==objId) {
                            return replace;
                        }
                    }
                }
            }
        }
        return null;
    }
    
    // 转换成CommonModel树`
    public replacesToCommonModel(): CommonModel {
        var ret: CommonModel=CommonModel.from(0,"可替换数据",CommonModel.SPREAD_EXPAND,0,false); 
        
        for(var i=0;i<this.replaces.length;i++){
            var r: SJGReplaceGroup=this.replaces[i];
            var s: CommonModel=r.toCommonModel(1);
            ret.addChild(s);
        }
        return ret;
    }
    // 修改“可替换item”的id
    public updateReplaceItemId(oldId,newId) {
        for(var i=0;i<this.replaces.length;i++) {
            var r: SJGReplaceGroup=this.replaces[i];
            if(r.updateReplaceItemId(oldId,newId)){
                break;
            }
            
        }
    }
    
    // 深度更新id［处理自身和子对象，递归］
    // 参数：idMaps，新旧id的对应关系, 例如：[{oldId:1,newId:2}]
    public deepResetId(idMaps: Array<any>) {
        this.describe.id=this.getGlobalData().idGenerator().newId();// 分配id;
        
        
        this.root.deepResetId(idMaps);
    }   
    // 拷贝当前页
    public copyPage():SJGPage {
        var idMaps=[]; // 新旧id的对应关系,例如：[{ oldId: 1,newId: 2 }]
        
        // 获取页信息
        var newPage: SJGPage=new SJGPage(this.getGlobalData());
        var jsonStr: string=(this.toJson()||'').replace(/\n/g,'\\n');// 处理Text对象的换行符
        newPage.fromJson(JSON.parse(jsonStr),0);
        newPage.deepResetId(idMaps);
        
        // 更新replace中的数据
        for(var i=0;i<newPage.replaces.length; i++) {
            var replace: SJGReplaceGroup=newPage.replaces[i];
            
            for(var k=0;k<idMaps.length;k++){
                var r=idMaps[k];
                replace.updateReplaceItemId(r.oldId,r.newId, true);
            }
            // 保存到可替换数组
            this.getGlobalData().objManager().saveReplaceGroupObject(replace);
        }
        
        return newPage;
    }
    
    //  升级数据，需要升级到接口实现
    public upgradeData() {
        if(this.root){
            this.root.upgradeData();
        }
        
        var docVer=this.getGlobalData().templateEidtor().getKernel().m_template.head.ver;
        if(docVer<4) {
            this.updateReplaceFlg();
        }
    }
    
    // 更新replaceFlg
    public updateReplaceFlg() {
        if(this.replaces && this.replaces.length>0) {
            for(var i=0;i<this.replaces.length;i++) {
                // ReplageGroup本身
                var sjgRepGrp: SJGReplaceGroup=this.replaces[i];
                var repGrpKnl=this.getGlobalData().objManager().getObject(sjgRepGrp.id);
                if(repGrpKnl) {
                    repGrpKnl.replaceFlg=ObjBase.REPLACE_OBJ_YES;
                }

                // 标题组/备注组
                if(sjgRepGrp.kind==SJGReplaceGroup.TITLEGROUP
                    ||sjgRepGrp.kind==SJGReplaceGroup.COMMENTGROUP) {
                    for(var n in sjgRepGrp.value) {
                        var text: SJGReplaceItemText=<SJGReplaceItemText>sjgRepGrp.value[n];
                        var txtKerObj: TextExtObj=<TextExtObj>GlobalData.objManager().getObject(text.id);
                        if(txtKerObj) {
                            txtKerObj.replaceFlg=ObjBase.REPLACE_OBJ_YES;
                        }else{
                            console.log("[updRepFlg][Tt/Cmt] Txt-Obj not found: "+text.id);
                        }
                    }
                    // 增强文字组
                } else if(sjgRepGrp.kind==SJGReplaceGroup.TEXTGROUP2) {
                    for(var n in sjgRepGrp.value) {
                        var subGrp: SJGSubGroupText=<SJGSubGroupText>sjgRepGrp.value[n];
                        for(var m in subGrp.value) {
                            var txtItem: SJGReplaceItemTitleText=subGrp.value[m];
                            //if(txtItem.tt==TextExtObj.TEXT_TYPE_BODY) 
                            {
                                var txtKerObj: TextExtObj=<TextExtObj>GlobalData.objManager().getObject(txtItem.id);
                                if(txtKerObj){
                                    txtKerObj.replaceFlg=ObjBase.REPLACE_OBJ_YES;
                                } else {
                                    console.log("[updRepFlg][T2] Txt-Obj not found: "+txtItem.id);
                                }
                            }
                        }
                    }
                    // 图文组2
                } else if(sjgRepGrp.kind==SJGReplaceGroup.IMAGETEXTGROUP2) {
                    for(var n in sjgRepGrp.value) {
                        var itSubGrp: SJGSubGroupImageText=<SJGSubGroupImageText>sjgRepGrp.value[n];
                        if(itSubGrp.image) {
                            var imgKerObj: ImageObj=<ImageObj>GlobalData.objManager().getObject(itSubGrp.image.id);
                            if(imgKerObj){
                                imgKerObj.replaceFlg=ObjBase.REPLACE_OBJ_YES;
                                
                                // fix bug
                                itSubGrp.image.pos.copy(imgKerObj.pos);
                                itSubGrp.image.mask=imgKerObj.mask.copy();
                                
                            } else {
                                console.log("[updRepFlg][IT2] Img-Obj not found: "+itSubGrp.image.id);
                            }
                        }
                        if(itSubGrp.textArr) {
                            for(var m in itSubGrp.textArr.value) {
                                var txtItem: SJGReplaceItemTitleText=itSubGrp.textArr.value[m];
                                //if(txtItem.tt==TextExtObj.TEXT_TYPE_BODY) 
                                {
                                    var kerObj: TextExtObj=<TextExtObj>GlobalData.objManager().getObject(txtItem.id);
                                    if(kerObj) {
                                        kerObj.replaceFlg=ObjBase.REPLACE_OBJ_YES;
                                    } else {
                                        console.log("[updRepFlg][IT2] Txt-Obj not found: "+txtItem.id);
                                    }
                                }
                            }
                        }
                    }
                    // 图片组
                } else if(sjgRepGrp.kind==SJGReplaceGroup.IMAGEGROUP) {
                    for(var n in sjgRepGrp.value) {
                        var imgItem: SJGReplaceItemImage=<SJGReplaceItemImage>sjgRepGrp.value[n];
                        var imgKerObj: ImageObj=<ImageObj>GlobalData.objManager().getObject(imgItem.id);
                        if(imgKerObj) {
                            imgKerObj.replaceFlg=ObjBase.REPLACE_OBJ_YES;
                            
                            // fix bug
                            imgItem.pos.copy(imgKerObj.pos);
                            imgItem.mask=imgKerObj.mask.copy();
                            
                        } else {
                            console.log("[updRepFlg][I] Img-Obj not found "+imgItem.id);
                        }
                    }
                    // 图表组
                } else if(sjgRepGrp.kind==SJGReplaceGroup.CHARTGROUP) {
                    for(var n in sjgRepGrp.value) {
                        var chtItem: SJGReplaceItemChart=<SJGReplaceItemChart>sjgRepGrp.value[n];
                        var chtKerObj: ChartObj=<ChartObj>GlobalData.objManager().getObject(chtItem.id);
                        if(chtKerObj) {
                            chtKerObj.replaceFlg=ObjBase.REPLACE_OBJ_YES;
                        } else {
                            console.log("[updRepFlg][C] Chart-Obj not found: "+chtItem.id);
                        }
                    }
                } else {
                    // TODO
                }
            }
        }
        
    }
    
//SJG_MARK_APPEND--------------------
    // 客户输入的本页面的可替换部分
    public userReplaces: Array<SJGReplaceGroup> = new Array<SJGReplaceGroup>();

    // 初始化用户的可替换数组
    public initUserReplaces(json, versionId){
        var jsonObj =null;
        // fix bug start
        //      20160202 16:06
        //      https://tower.im/projects/5876472bbb39453d985a4397d5a00273/todos/4366528f079f43649dc75bcdcae0725f/
        //      问题2
        try{
            jsonObj= JSON.parse(json)
        }catch(e){
            console.log("***exception: initUserReplaces,parameter:"+json+",version:"+versionId);
        }
        // fix bug end

        this.userReplaces.splice(0, this.userReplaces.length);

        if(jsonObj){
            for(var i in jsonObj){
                var replaceGrp:SJGReplaceGroup = ParserOfUserReplaces.fromUnknownJson(jsonObj[i], versionId, this.getGlobalData());
                this.userReplaces.push(replaceGrp);
            }
        }

        // 删除空格子
        //var len = this.userReplaces.length;
        //if(len>0){
        //    for(var i:any=len-1;i>=0;i--){
        //        var one = this.userReplaces[i];
        //        if(one && one.isContentEmpty()){
        //            this.userReplaces.splice(i,1);
        //        }
        //    }
        //}
    }
    // 用户的可替换数组是否为空
    public isUserReplacesContentEmpty():boolean {
        if(this.userReplaces==null || this.userReplaces.length==0){
            return true;
        }
        var allEmpty:boolean = true;
        for(var i in this.userReplaces){
            var replaceGrp:SJGReplaceGroup = this.userReplaces[i];
            if(!replaceGrp.isContentEmpty()){
                allEmpty=false;
                break;
            }

        }
        return allEmpty;
    }

    // 增加用户的可替换数组－只有基本属性
    public addTestDataOfUserReplaces(){
        // 为可替换数组增加元素
        for(var i in this.replaces){

            var replace:SJGReplaceGroup = <SJGReplaceGroup>this.replaces[i];
            // 跳过标题组
            if(replace.kind == SJGReplaceGroup.TITLEGROUP){

            }else if(replace.kind == SJGReplaceGroup.TEXTGROUP){

                var userReplace:SJGReplaceGroup = new SJGReplaceGroup();
                this.userReplaces.push(userReplace);
                userReplace.kind= replace.kind;
                userReplace.min= replace.min;
                userReplace.max= replace.max;
                userReplace.id= replace.id; //


                for(var j in replace.value){
                    var item:SJGReplaceItemBase = replace.value[j];
                    // 对应模版中已经存在的文字
                    var userItem: SJGReplaceItemText=new SJGReplaceItemText();
                    userItem.type=SJGReplaceItemBase.TYPE_TEXT;
                    userItem.id=item.id;
                    userItem.value="文字1";
                    userItem.min=1;
                    userItem.max=20;
                    userReplace.value.push(userItem);

                    // 对应模版中没有的文字
                    var userItem: SJGReplaceItemText=new SJGReplaceItemText();
                    userItem.type=SJGReplaceItemBase.TYPE_TEXT;
                    userItem.id= DEFINE.ID_NONE;
                    userItem.value="文字2";
                    userItem.min=1;
                    userItem.max=20;
                    userReplace.value.push(userItem);
                }


            }else if(replace.kind == SJGReplaceGroup.IMAGEGROUP){

                var userReplace:SJGReplaceGroup = new SJGReplaceGroup();
                this.userReplaces.push(userReplace);
                userReplace.kind= replace.kind;
                userReplace.min= replace.min;
                userReplace.max= replace.max;
                userReplace.id= replace.id; //


                for(var j in replace.value){
                    var item:SJGReplaceItemBase = replace.value[j];
                    // 对应模版中已经存在的图片
                    var userItem2: SJGReplaceItemImage=new SJGReplaceItemImage();
                    userItem2.type=SJGReplaceItemBase.TYPE_IMAGE;
                    userItem2.id=item.id;
                    userItem2.value="http://127.0.0.1:3001/images/1.jpg";
                    userReplace.value.push(userItem2);

                    // 对应模版中没有的图片
                    var userItem2: SJGReplaceItemImage=new SJGReplaceItemImage();
                    userItem2.type=SJGReplaceItemBase.TYPE_IMAGE;
                    userItem2.id= DEFINE.ID_NONE;
                    userItem2.value="http://127.0.0.1:3001/images/1.jpg";
                    userReplace.value.push(userItem2);
                }


            }

        }



    }
    // 排版
    // 参数：asyncCallback为async的回调函数，例如：asyncCallback(null, 'one');
    public typeset(asyncCallback:Function){
        var THIS = this;
        async.series([// 顺次执行
                // 补充replaces中高级参数［这些高级参数只有模版有，用户端的数据没有，例如SJGReplaceGroup的extend_style属性］
                function(callback){
                    THIS.getAdvanceInfo(function(){
                        callback(null,null);
                    });
                },
                // 获取replaces中的文字轮廓,通过RPC访问
                function(callback){
                    THIS.getCharContour(function(){
                        callback(null,null);
                    });
                },
                //// 获取replaces中的“文字组／图文组”对应的“自动替换图标”
                //function(callback){
                //    THIS.getAutoReplaceGraph(function(){
                //        callback(null,null);
                //    });
                //},

                //// 获取replaces中的图片下载到本地，通过七牛访问
                //function(callback){
                //    THIS.downloadImage(function(){
                //        callback(null,null);
                //    });
                //}
            ],
            function(err, results){
                var ts:SJGTypeSet = new SJGTypeSet();
                ts.do(THIS, asyncCallback);
            });
    }

    // 1，补充replaces中高级参数［这些高级参数只有模版有，用户端的数据没有，例如SJGReplaceGroup的extend_style属性］
    // 2，对于ios端新建的对象（没有旧对象的id，用于从旧id中取得信息，例如文字参数、图片裁剪路径），
    //      需要从模版文档中找到对应的旧对象的id设置进去，例如：ios端端标题组和文字组被删除后重新插入时，已经没有旧对象端id了，
    public getAdvanceInfo(callback:Function) {
        for(var i in this.userReplaces){
            var userReplace:SJGReplaceGroup = this.userReplaces[i];
            // 根据id找到模版中的SJGReplaceGroup，复制信息
            var replace:SJGReplaceGroup = this.getTemplateReplaceGroup(userReplace.id);
            if(replace){
                userReplace.advance = replace.advance.copy();
                userReplace.advance.count = userReplace.value.length;
                //userReplace.advance.extend_style = replace.advance.extend_style;
                //userReplace.advance.extend_method = replace.advance.extend_method;
                //userReplace.advance.extend_path = replace.advance.extend_path;
                //userReplace.advance.align_point = replace.advance.align_point;
                //userReplace.advance.header_type = replace.advance.header_type;
                //userReplace.advance.limit = replace.advance.limit;
                //userReplace.advance.count = userReplace.value.length;// count表示元素个数，使用客户端的。


                // 复制SJGReplaceItemBase的id
                this.copyAdvanceInfoFromReplaceToUser(replace.value, userReplace.value);

            }
        }

        callback();
    }
    private getTemplateReplaceGroup(id:number):SJGReplaceGroup{
        for(var i in this.replaces){
            var replace:SJGReplaceGroup = this.replaces[i];
            if(replace.id == id){
                return replace;
            }
        }
        return null;
    }
    private copyAdvanceInfoFromReplaceToUser(value:Array<SJGReplaceItemBase>, userValue:Array<SJGReplaceItemBase>){
        if(value==null || value.length==0 || userValue==null || userValue.length==0){
            return;
        }
        // 按顺序复制，不够的部分复制最后一个有效的
        for(var i in userValue){
            var userItem:SJGReplaceItemBase = userValue[i];
            if(i<value.length){
                userItem.id = value[i].id;
                // 图文组还需处理子对象
                if(userItem instanceof SJGSubGroupImageTextOld) {
                    userItem.image.id = (<SJGSubGroupImageTextOld>value[i]).image.id;
                    userItem.text.id = (<SJGSubGroupImageTextOld>value[i]).text.id;
                }
                else if(userItem instanceof  SJGSubGroupText){
                    var t2:SJGSubGroupText = <SJGSubGroupText> userItem;
                    for(var k in t2.value){
                        t2.value[k].id = (<SJGSubGroupText>value[i]).value[k].id;
                    }
                }
                else if(userItem instanceof  SJGSubGroupImageText){
                    var it2:SJGSubGroupImageText = <SJGSubGroupImageText> userItem;
                    it2.image.id = (<SJGSubGroupImageText>value[i]).image.id;
                    for(var k in it2.textArr.value){
                        it2.textArr.value[k].id = (<SJGSubGroupImageText>value[i]).textArr.value[k].id;
                    }
                }

            }else{
                userItem.id = value[value.length-1].id;
                // 图文组还需处理子对象
                if(userItem instanceof SJGSubGroupImageTextOld) {
                    userItem.image.id = (<SJGSubGroupImageTextOld>value[value.length-1]).image.id;
                    userItem.text.id = (<SJGSubGroupImageTextOld>value[value.length-1]).text.id;
                }
            }
        }
    }


    // 获取可替换文字的字体、字号等信息
    public getReplaceTextPara(text:SJGReplaceItemText){
        // 处理旧文字
        var obj:ObjBase = this.getGlobalData().objManager().getObject(text.id);
        if(obj){
            if(obj.ct ==GCJ_CLASS_TYPE.CLASS_TYPE_TextObj){
                var textObj:TextObj = <TextObj>obj;
                // --fix bug stat-----
                // 为了提高文字大清晰度，先放大TextObj.FONT_ZOOM_FACTOR
                textObj.fz = TextObj.FONT_ZOOM_FACTOR;
                // --fix bug end-----

                var para = {
                    fontName:   textObj.fn,
                    fontSize:   textObj.fs,
                    fontZoom:   textObj.fz,
                    boldItalic: textObj.bi, //  0.常规   1.粗体   2.斜体   3.粗斜体
                    position:   textObj.po, // 1. 靠左   2.居中   3.靠右
                    text:       text.value  // 文字内容
                };

                return para;
            }else if(obj.ct ==GCJ_CLASS_TYPE.CLASS_TYPE_TextExtObj){
                // 处理新文字
                var textObj2:TextExtObj = <TextExtObj>obj;
                if(textObj2){
                    // --fix bug stat-----
                    // 为了提高文字大清晰度，先放大TextObj.FONT_ZOOM_FACTOR
                    textObj2.fz = TextObj.FONT_ZOOM_FACTOR;
                    // --fix bug end-----

                    var para = {
                        fontName:   textObj2.style.fn,
                        fontSize:   textObj2.style.fs,
                        fontZoom:   textObj2.fz,
                        boldItalic: textObj2.style.bi, //  0.常规   1.粗体   2.斜体   3.粗斜体
                        position:   textObj2.style.po, // 1. 靠左   2.居中   3.靠右
                        text:       text.value  // 文字内容
                    };

                    return para;
                }
            }
        }


        return null;
    }
    // 抽取txt中的名词，用"-"作为连接符进行拼接
    public static COMMON_NAME:string = "通用";
    public static p_delimiter_arr:string = ",";//多个文字的分隔符
    public static p_delimiter_seg:string = "-";//文字的多个分词的分隔符
    private doSegmentOfText(txt):string{
        var segs = segment.doSegment(txt, {stripPunctuation: true});
        var segWords=[];
        for(var i=segs.length-1 ; i>=0;i--){
            var one = segs[i];
            if( one.p == POSTAG.D_N
                ||one.p == POSTAG.D_S
                ||one.p == POSTAG.A_NR
                ||one.p == POSTAG.A_NS){
                segWords.push(one.w);
            }
        }

        return segWords.join(SJGPage.p_delimiter_seg);
    }
    // 获取编组下的自动替换图标抬头和其对应的文本
    // 参数：groupId：编组id
    // 参数：classType：
    // 返回：Object，含有以下属性：
    //          graphObjArr: 图形对象数组
    //          textStrArr:  文本数组，同一个图形的多个词之间以 SJGPage.p_delimiter_seg分隔
    private getAutoReplaceHeadAndTextInGroup(groupId, classType):any{
        var graphObjArr = [];
        var textStrArr:Array<String> = [];
        var gt = 0;

        var objMgr:ObjManager = this.getGlobalData().objManager();
        var G:GroupObj =<GroupObj> objMgr.getObject(groupId);
        var arr:Array<number> = G.getChildOfType(classType, false, true);
        for(var n in arr){
            var one:ObjBase = objMgr.getObject(arr[n]);
            if(!one)    continue;

            var textObj:any = null;
            if(GCJ_CLASS_TYPE.CLASS_TYPE_TextObj == one.ct){
                textObj = <TextObj> one ;
            }else if(GCJ_CLASS_TYPE.CLASS_TYPE_TextExtObj == one.ct){
                textObj = <TextExtObj> one ;
            }else{
                continue;
            }

            var graphObj:GraphObj = null;  // 可自动替换的图标
            if(textObj.head){
                // 如果抬头是图形
                if(textObj.head instanceof GraphObj){
                    var oneGraph:GraphObj = <GraphObj>(textObj.head);
                    if(oneGraph.ar==GraphObj.GRAPHOBJ_AUTO_REPLACE_ON){
                        graphObj=oneGraph;
                    }
                }else if(textObj.head instanceof  GroupObj){
                    // 如果抬头是组，则
                    var headGroup:GroupObj = (<GroupObj>(textObj.head));
                    var graphArr:Array<number> = headGroup.getChildOfType(GCJ_CLASS_TYPE.CLASS_TYPE_GraphObj, false, true);
                    if(graphArr.length>0){
                        for(var t=0;t<graphArr.length;t++){
                            var oneGraph:GraphObj = <GraphObj> objMgr.getObject(graphArr[t]) ;
                            if(oneGraph.ar==GraphObj.GRAPHOBJ_AUTO_REPLACE_ON){
                                graphObj=oneGraph;
                                break;
                            }
                        }
                    }
                }

            }
            if(graphObj!=null ){
                // 只处理“自动替换属性”被打开的图形
                gt = graphObj.gt;
                graphObjArr.push(graphObj);

                // 找到图形对应的文字，进行分词处理
                var oneTextArrStr = null;
                var segRet = this.doSegmentOfText(textObj.te);
                if(segRet!=null && segRet.length>0){
                    oneTextArrStr = oneTextArrStr==null?segRet:(oneTextArrStr+SJGPage.p_delimiter_seg+segRet);
                }
                // 找到同一组中的文字，进行分词处理
                var otherTextArr = textObj.getSiblingOfType(GCJ_CLASS_TYPE.CLASS_TYPE_TextObj, false);
                if(otherTextArr.length>0){
                    for(var o=0;o<otherTextArr.length;o++){
                        var one2:ObjBase = objMgr.getObject(otherTextArr[o]);
                        if(!one2)   continue;
                        var otherText:any = null;
                        if(GCJ_CLASS_TYPE.CLASS_TYPE_TextObj == one2.ct){
                            otherText = <TextObj> one2 ;
                        }else if(GCJ_CLASS_TYPE.CLASS_TYPE_TextExtObj == one2.ct){
                            otherText = <TextExtObj> one2 ;
                        }else{
                            continue;
                        }

                        if(otherText){
                            var segRet = this.doSegmentOfText(otherText.te);
                            if (segRet != null && segRet.length > 0) {
                                oneTextArrStr = oneTextArrStr == null ? segRet : (oneTextArrStr + SJGPage.p_delimiter_seg + segRet);
                            }
                        }

                    }

                }
                // 没有文字，则使用默认
                if(oneTextArrStr==null){
                    oneTextArrStr = SJGPage.COMMON_NAME;
                }
                textStrArr.push(oneTextArrStr);
            }
        }

        return { graphObjArr:graphObjArr,textStrArr:textStrArr , gt:gt};
    }
    // 获取编组下的自动替换图标和其对应的文本
    // 参数：groupId：编组id
    // 参数：classType：
    // 返回：Object，含有以下属性：
    //          graphObjArr: 图形对象数组
    //          textStrArr:  文本数组，同一个图形的多个词之间以 SJGPage.p_delimiter_seg分隔
    private getAutoReplaceGraphAndTextInGroup(groupId, classType):any{
        var graphObjArr = [];
        var textStrArr:Array<String> = [];
        var gt = 0;

        var objMgr:ObjManager = this.getGlobalData().objManager();
        var G:GroupObj = <GroupObj>objMgr.getObject(groupId);
        var arr:Array<number> = G.getChildOfType(GCJ_CLASS_TYPE.CLASS_TYPE_GraphObj, false, true);
        for(var n in arr){
            var graphObj:GraphObj = <GraphObj> objMgr.getObject(arr[n]) ;
            if(!graphObj)   continue;
            if(graphObj.ar == GraphObj.GRAPHOBJ_AUTO_REPLACE_ON){
                // 只处理“自动替换属性”被打开的图形
                gt = graphObj.gt;

                graphObjArr.push(graphObj);

                // 找到图形对应的文字，进行分词处理
                var oneTextArrStr = null;
                var textArr:Array<number> = graphObj.getSiblingOfType(classType);
                for(var k in textArr){
                    var one:ObjBase = objMgr.getObject(textArr[n]);
                    if(!one)    continue;

                    var textObj:any = null;
                    if(GCJ_CLASS_TYPE.CLASS_TYPE_TextObj == one.ct){
                        textObj = <TextObj> one ;
                    }else if(GCJ_CLASS_TYPE.CLASS_TYPE_TextExtObj == one.ct){
                        textObj = <TextExtObj> one ;
                    }else{
                        continue;
                    }
                    var segRet = this.doSegmentOfText(textObj.te);
                    if(segRet!=null && segRet.length>0){
                        oneTextArrStr = oneTextArrStr==null?segRet:(oneTextArrStr+SJGPage.p_delimiter_seg+segRet);
                    }
                }
                if(oneTextArrStr==null){
                    oneTextArrStr = SJGPage.COMMON_NAME;
                }
                textStrArr.push(oneTextArrStr);
            }
        }


        return { graphObjArr:graphObjArr,textStrArr:textStrArr , gt:gt};
    }
    // 获取replaces中的“文字组／图文组”中的“文字”的“抬头”中的“自动替换图标”
    public getAutoReplaceGraphInTextHead(callback:Function){
        var THIS = this;


        // 查找以下编组中的图形：文字编组、图文编组、文字编组2、图文编组2
        var graphObjArr = [];
        var textStrArr:Array<String> = [];
        var gt = 0;
        for (var replace in this.userReplaces) {
            var group:SJGReplaceGroup = <SJGReplaceGroup> this.userReplaces[replace];
            if(group.kind== SJGReplaceGroup.TEXTGROUP
                ||group.kind==SJGReplaceGroup.IMAGETEXTGROUP
                ||group.kind==SJGReplaceGroup.TEXTGROUP2
                ||group.kind==SJGReplaceGroup.IMAGETEXTGROUP2){

                // 处理旧文字TextObj上的抬头
                var ret1:any = this.getAutoReplaceHeadAndTextInGroup(group.id,GCJ_CLASS_TYPE.CLASS_TYPE_TextObj);
                // 合并
                if(ret1.graphObjArr.length>0 && ret1.textStrArr.length>0){
                    graphObjArr = ret1.graphObjArr.concat(graphObjArr);
                    textStrArr = ret1.textStrArr.concat(textStrArr);
                    gt = ret1.gt;
                }


                // 处理新文字TextExtObj上的抬头
                var ret2:any = this.getAutoReplaceHeadAndTextInGroup(group.id,GCJ_CLASS_TYPE.CLASS_TYPE_TextExtObj);
                // 合并
                if(ret2.graphObjArr.length>0 && ret2.textStrArr.length>0){
                    graphObjArr = ret2.graphObjArr.concat(graphObjArr);
                    textStrArr = ret2.textStrArr.concat(textStrArr);
                    gt = ret2.gt;
                }
            }
        }

        // 到数据搜索相同类型的、名称匹配的图标
        this.autoReplaceCore(gt,graphObjArr, textStrArr, callback);
    }

    // 获取replaces中的“文字组／图文组”对应的“自动替换图标”图形对象
    public getAutoReplaceGraph(callback:Function) {
        var THIS = this;


        // 查找以下编组中的图形：文字编组、图文编组、文字编组2、图文编组2
        var graphObjArr = [];
        var textStrArr:Array<String> = [];
        var gt = 0;
        for (var replace in this.userReplaces) {
            var group:SJGReplaceGroup = <SJGReplaceGroup> this.userReplaces[replace];
            if(group.kind== SJGReplaceGroup.TEXTGROUP
            ||group.kind==SJGReplaceGroup.IMAGETEXTGROUP
            ||group.kind==SJGReplaceGroup.TEXTGROUP2
            ||group.kind==SJGReplaceGroup.IMAGETEXTGROUP2){

                // 处理旧文字TextObj上的抬头
                var ret1:any = this.getAutoReplaceGraphAndTextInGroup(group.id, GCJ_CLASS_TYPE.CLASS_TYPE_TextObj);
                // 合并
                if(ret1.graphObjArr.length>0 && ret1.textStrArr.length>0){
                    graphObjArr = ret1.graphObjArr.concat(graphObjArr);
                    textStrArr = ret1.textStrArr.concat(textStrArr);
                    gt = ret1.gt;
                }

                // 处理新文字TextExtObj上的抬头
                var ret2:any = this.getAutoReplaceGraphAndTextInGroup(group.id,GCJ_CLASS_TYPE.CLASS_TYPE_TextExtObj);
                // 合并
                if(ret2.graphObjArr.length>0 && ret2.textStrArr.length>0){
                    graphObjArr = ret2.graphObjArr.concat(graphObjArr);
                    textStrArr = ret2.textStrArr.concat(textStrArr);
                    gt = ret2.gt;
                }

            }
        }

        // 到数据搜索相同类型的、名称匹配的图标
        this.autoReplaceCore(gt, graphObjArr, textStrArr, callback);
    }
    // 实现自动替换
    private autoReplaceCore(gt, graphObjArr, textStrArr:Array<String>, callback:Function){
        if(textStrArr.length==0){
            callback(null, null);
        }else{
            var entity = new ItbGraphModel();
            entity.findLikenessGraph(gt, textStrArr.join(SJGPage.p_delimiter_arr),
                SJGPage.p_delimiter_arr,SJGPage.p_delimiter_seg, function(err,rows){
                    if(err){
                        console.log('-----> entity.findLikenessGraph error:'+err);
                    }
                    if(rows&& rows.length== graphObjArr.length+1){
                        // 替换图形数据、进行缩放
                        for(var k in graphObjArr){
                            var graphObj = graphObjArr[k] ;
                            var oneRow = rows[k][0];
                            if(oneRow.graph_id){
                                // rows[k].data->graphObj.cp
                                // 将新图标的中心点和旧图标的中心点重合
                                var rectOld = graphObj.pos.w>graphObj.pos.h?graphObj.pos.w:graphObj.pos.h;
                                var centerXOld = graphObj.pos.x+graphObj.pos.w/2;
                                var centerYOld = graphObj.pos.y+graphObj.pos.h/2;

                                // 解析新图标数据
                                graphObj.cp.fromJson(JSON.parse(oneRow.data),0);
                                // 使得新旧图标的外接正方形相同
                                var rectNew = graphObj.cp.w>graphObj.cp.h?graphObj.cp.w:graphObj.cp.h;
                                var ratio = rectOld/rectNew;
                                graphObj.cp.adjustPosition(ratio,ratio,2);

                                // 将新图标的中心点和旧图标的中心点重合
                                graphObj.pos.x = centerXOld - graphObj.cp.w/2;
                                graphObj.pos.y = centerYOld - graphObj.cp.h/2;
                            }
                        }
                    }else{
                        console.log('-----> entity.findLikenessGraph error:'+'rows length error !');
                    }

                    callback(null, null);
                });
        }
    }

    // 获取replaces中的文字轮廓,通过RPC访问
    private getCharContour(callback:Function){
        var THIS = this;
        // 可替换文字数组
        var replaceItemText = [];
        for (var replace in this.userReplaces) {
            var group:SJGReplaceGroup = <SJGReplaceGroup> this.userReplaces[replace];
            for(var item in group.value){
                var op:SJGReplaceItemBase = group.value[item];
                if(op instanceof SJGReplaceItemText){
                    replaceItemText.push(op);
                } else if(op instanceof  SJGSubGroupImageTextOld){
                    replaceItemText.push((<SJGSubGroupImageTextOld>op).text);
                } else if(op instanceof SJGSubGroupText){
                    replaceItemText = replaceItemText.concat((<SJGSubGroupText>op).value)
                } else if(op instanceof  SJGSubGroupImageText){
                    var textArr: SJGSubGroupText = (<SJGSubGroupImageText>op).textArr;
                    replaceItemText = replaceItemText.concat(textArr.value);
                }
            }
        }
        // 并发获取文字轮廓
        var asyncFuncs = [];
        for(var item in replaceItemText){
            asyncFuncs.push((function (text:SJGReplaceItemText) {
                return function (asyncCallback) {  // asyncCallback(null, 'one');// asyncCallback(null, 'two');

                    var para = THIS.getReplaceTextPara(text);
                    if(para){
                        rpcFunc.contour(para, function (ret) {
                            if(ret){
                                text.originContour = ret;
                            }
                            asyncCallback(null, ret);
                        });

                    }else{
                        asyncCallback(null, null);
                    }
                }
            })(replaceItemText[item])); // 利用闭包解决动态参数传递问题
        }

        async.parallelLimit(asyncFuncs,5, function (err, results) {
            callback();
        });
    }
    // 获取replaces中的图片下载到本地，通过七牛访问
    //private downloadImage(callback:Function){
    //    var asyncFuncs = [];
    //    for (var replace in this.userReplaces) {
    //        var group:SJGReplaceGroup = <SJGReplaceGroup> this.userReplaces[replace];
    //        for(var item in group.value){
    //            asyncFuncs.push((function (op:SJGReplaceItemBase) {
    //                return function (asyncCallback) {  // asyncCallback(null, 'one');// asyncCallback(null, 'two');
    //                    if(op instanceof SJGReplaceItemImage){
    //                        var image:SJGReplaceItemImage = <SJGReplaceItemImage> op;
    //                        var dest = CONFIG.DOWNLOAD_IAMGE_DIR+CommonUtil.genDayStr()+"/"+CommonUtil.genRandomStr();
    //                        FileDownLoader.download(image.value, dest, function(err){
    //                            if(err){
    //                                image.value = null;
    //                            }else{
    //                                image.value = dest;
    //                            }
    //                            asyncCallback(null, dest);
    //                        });
    //                    }else{
    //                        asyncCallback(null, null);
    //                    }
    //                }
    //            })(group.value[item])); // 利用闭包解决动态参数传递问题
    //        }
    //    }
    //    async.parallel(asyncFuncs, function (err, results) {
    //        callback();
    //    });
    //}

    // 删除原文档中多余的主标题对象、第1副标题对象、第2副标题对象
    public removeInvalidTitle(titleGroup:SJGReplaceGroup){
        var objMgr:ObjManager = this.getGlobalData().objManager();
        var titleGroupTmp:SJGReplaceGroup = this.getTemplateReplaceGroup(titleGroup.id);
        var lenTmp = titleGroupTmp.value.length;
        var len = lenTmp - titleGroup.value.length;
        for(var i=0;i<len;i++){
            var titleTmp:SJGReplaceItemText =<SJGReplaceItemText> titleGroupTmp.value[lenTmp-1-i];
            this.root.removeChild(titleTmp.id);
        }
    }
    //------------------------------------------------------------------
    /* 检查数据的有效性.
     * 方式:GET
     * 参数:pc:1表示从pc来的请求/为空或者其它值表示从手机来的请求
     * 参数:docId:用户文档id
     * 返回:对象，属性如下：
     *          error:错误内容，null表示没有错误
     *          message:消息
     * */
    public validate() {
        return this.root.validate();
    }

    // 是否有重复页.
    public isDuplicatePage():boolean{
        return this.getGlobalData().objManager().getObject(this.root.id) !=null;
    }

    // 生成最小限度的json字符串，给图片服务使用
    public toJsonMinmum():string {
        // 去掉父json字符串的头尾
        var superJson = super.toJson();
        superJson = superJson.substr(1,superJson.length-2);

        var ret = '{';
        ret +=superJson;



        // root
        ret +=',';
        ret += '"root":';
        ret += this.root.toJson();



        ret+='}';
        return ret;
    }

}//SJG_MARK_END-------------------------


var Segment = require('node-segment').Segment;// 载入分词模块
var POSTAG = require('node-segment').POSTAG;// 载入词性接口
var segment = new Segment();// 创建实例
segment.useDefault();// 使用默认的识别模块及字典，载入字典文件需要1秒，仅初始化时执行一次即可
